package com.kuang.productConsumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * A B C D 线程通信 JUC Lock+Condition  精准通知打印：循环执行A->B->C
 *
 * @author sdm
 * @version 1.0
 * @date 2023/6/24 15:23
 */
public class ProductConsumerConditionDemoABCDJUCOrderly {
    public static void main(String[] args) {
        // 获取资源类
        Goods3 goods3 = new Goods3();

        // 创建多线程，将资源类抛进去
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    goods3.printA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    goods3.printB();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    goods3.printC();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();

        /* 实现效果：
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
            A=>线程A执行
            B=>线程B执行
            C=>线程C执行
         */
    }

}

// 等待，业务，通知
class Goods3{   //资源类

    Lock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();  // 同步监视器:一个监视器只监视一个
    Condition condition2 = lock.newCondition();  // 同步监视器:一个监视器只监视一个
    Condition condition3 = lock.newCondition();  // 同步监视器:一个监视器只监视一个

    private int number = 1; // 1A 3B 5C

    public void printA() throws InterruptedException {
        lock.lock();
        try {
            // 业务  等待,执行,通知
            while (number != 1){
                condition1.await();
            }
            number = 2;
            System.out.println(Thread.currentThread().getName() + "=>线程A执行");
            // 唤醒指定的人，B
            condition2.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void printB() throws InterruptedException {
        lock.lock();
        try {
            // 业务  等待,执行,通知
            while (number != 2){
                condition2.await();
            }
            number = 3;
            System.out.println(Thread.currentThread().getName() + "=>线程B执行");
            // 唤醒指定的人，C
            condition3.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void printC() throws InterruptedException {
        lock.lock();
        try {
            // 业务  等待,执行,通知
            while (number != 3){
                condition3.await();
            }
            number = 1;
            System.out.println(Thread.currentThread().getName() + "=>线程C执行");
            // 唤醒指定的人，A
            condition1.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }




}
